#include "FileLoader.h"
#include "Minecraft/Containers/Chunk.h"
#pragma comment(lib,"zlib/zdll.lib")
#include "../zlib/zlib.h" // gzip compression
#include <memory.h> // Used for memcpy_s()

// Nice easy to set variable for buffer size (defaults to 32K)
unsigned int MinecraftFile::nDefaultBufferSize = 32768;

MinecraftFile::MinecraftFile() : m_FileBuff(NULL), m_nCurrentSize(nDefaultBufferSize),
	m_nFileSize(0),	m_pNBTFile(NULL)
{
	// Nothing fancy here
}

MinecraftFile::~MinecraftFile()
{
	// Call our clean up helpers
    ClearBuffer();
	CleanUpNBT();
}

bool MinecraftFile::Load(const char *_szFileName, unsigned int _gzSize/* = 131072*/)
{
	// Clean up our buffer
	ClearBuffer();

	// Make a new one
	m_FileBuff = new char[nDefaultBufferSize];

	// Open the file, return false if we couldn't open it (NULL)
	gzFile file = gzopen(_szFileName, "rb");
	if (file == NULL)
	{
		ClearBuffer();
		return false;
	}

	// Resize our decompression buffer so that gzip goes super fast (defaults to 128K)
	gzbuffer(file, _gzSize);

	// Read the whole file
	int read = 0;
	do
	{
		// Read is how much we read, 0 if we're already at eof, -1 on error
		read = gzread(file, (void *)(m_FileBuff + m_nFileSize), m_nCurrentSize - m_nFileSize);
		m_nFileSize += read;

		// If we filled our buffer, double its size
		if (m_nFileSize == m_nCurrentSize)
			ResizeBuffer();

	} while (gzeof(file) == false && read != -1);

	// We had an error, clear our buffer
	if (read == -1)
	{
		ClearBuffer();
		return false;
	}

	// Make sure we clear our flags and close the file
	gzclearerr(file);
	gzclose_r(file);

	return true;
}

void MinecraftFile::Decode()
{
	// Delete our old file
	CleanUpNBT();

	// Get the new one
	m_pNBTFile = NBT::Decode(m_FileBuff, m_nFileSize);

	// Clear our buffer (we don't need to waste space)
	ClearBuffer();
}

void MinecraftFile::WriteToText(const char *_szFileName)
{
	// Make sure we have the file and write it out
	if (m_pNBTFile != NULL)
		NBT::WriteToText(_szFileName, m_pNBTFile);
}

void MinecraftFile::CleanUpNBT()
{
	// Delete our internal NBT file
	if (m_pNBTFile != NULL)
	{
		delete m_pNBTFile;
		m_pNBTFile = NULL;
	}
}

void MinecraftFile::ResizeBuffer()
{
	// Our new values
	unsigned int newSize = m_nCurrentSize * 2;
	char *newBuff = new char[newSize];

	// Copy over the old data
	memcpy_s(newBuff, newSize, m_FileBuff, m_nCurrentSize);

	// Clear the old data
	delete[] m_FileBuff;

	// Update the old values to the new ones
	m_FileBuff = newBuff;
	m_nCurrentSize = newSize;	
}

void MinecraftFile::ClearBuffer()
{
	// Delete our internal file buffer
	if (m_FileBuff != NULL)
	{
		delete[] m_FileBuff;
		m_FileBuff = NULL;
	}

	// Reset our place markers
	m_nFileSize = 0;
	m_nCurrentSize = nDefaultBufferSize;
}

void MinecraftFile::DecodeIntoChunk(Chunk* _chunk)
{
		// Delete our old file
	CleanUpNBT();

	// Get the new one
	NBT::DecodeIntoChunk(m_FileBuff, m_nFileSize, _chunk);

	// Clear our buffer (we don't need to waste space)
	ClearBuffer();
}